"use client"; import { useParams } from "next/navigation"; import { useEffect } from "react"; import { usePage, usePageBlocks } from "@/hooks/use-pages"; import { usePresence } from "@/hooks/use-presence"; import { usePageRealtime } from "@/hooks/use-realtime"; import { useEditorStore } from "@/stores/editor-store"; import { PageSpinner } from "@/components/editor/page-spinner"; /** * Page route layout: loads the page (usePage) and its top-level blocks * (usePageBlocks), opens the realtime channel, and tracks the active page * in the editor store. The actual editor is rendered by the route page — * [id]/page.tsx (plain) and [id]/[block]/page.tsx (deep link with * focusBlockId) — so the Tiptap instance mounts exactly once per URL. */ export default function PageLayout({ children }: { children: React.ReactNode }) { const params = useParams<{ id: string; block?: string }>(); const pageId = params?.id ?? ""; // Data (kept here so every child route under [id] shares one query key). const page = usePage(pageId); usePageBlocks(pageId || ""); useEffect(() => { useEditorStore.getState().setActivePage(pageId || null); }, [pageId]); // Realtime channel for the active page (presence + block overlay). usePageRealtime(pageId || null); // Presence emission (TASK-0093): this tab's caret + visibility → // `presence` frames on the page channel (see hooks/use-presence.ts). usePresence(pageId || null); // Deep link: /w/:ws/page/:id/:block — remember the focus target so // PageView can scroll to and expand the block once it renders. useEffect(() => { if (params?.block) { useEditorStore.getState().setFocus(params.block); } }, [params?.block, pageId]); if (page.isLoading) return ; // A FAILED page load (404/5xx, or a transient "internal error") must be a // visible, retryable state — not the infinite spinner the missing branch // used to produce, and not a crash into Next's error overlay (QA issues // #5/#6: "navigating … became fail" / "lags … leads to error page"). if (page.isError) { const msg = page.error instanceof Error ? page.error.message : "The page could not be loaded."; return (

Couldn’t load this page

{msg}

); } return <>{children}; }